home *** CD-ROM | disk | FTP | other *** search
/ HyperLib 1997 Winter - Disc 1 / HYPERLIB-1997-Winter-CD1.ISO.7z / HYPERLIB-1997-Winter-CD1.ISO / オンラインウェア / PRG / WASTE Object Handlers 1.2.2.sit / WASTE Object Handlers 1.2.2 / Handler Source / WE_snd_Handler.c < prev    next >
Text File  |  1996-07-18  |  9KB  |  389 lines

  1. // Sound Object Handler for the WASTE Text Engine
  2. // by Michael F. Kamprath, kamprath@kagi.com
  3. // maintenance by John C. Daub, hsoi@eden.com
  4. //
  5. // v1.0, 16 March 1995
  6. // v1.0.1, 13 May 1995, changed the sound playing code a little.  Also added gestalt
  7. //                        check for sound recording device when CreateNewSoundObject()
  8. //                        is called.
  9. // v1.1, 5 June 95, Made some changes recomended by Chris Thomas, <THUNDERONE@delphi.com>:
  10. //            -    Playing an object's sound is done by ultilizing the object's data
  11. //                directly rather than making a copy.  Using PlaySoundHandle() for
  12. //                your sounds still makes a copy.
  13. //            -    Added the public routines StopCurrentSound() and IsSoundPlaying().
  14. //            -    Option to have the sound sound created at the handler's initilization.
  15. //            -    Added InstallSoundObject() to install sound object handler only.
  16. //
  17. // v1.2, 28 March 1996.  Bug fixes by John C. Daub <mailto:hsoi@eden.com>
  18. //            -    Removed a not operator from SoundIsPlaying() so the function works correctly
  19. //            -    Adjusted CheckSoundStatus() to work with the fixed SoundIsPlaying()
  20. //            -    Minor updates: more precompiler directives, WASTE 1.2a5 compatability
  21. //
  22. // v1.2.2, 16 July 1996. Added compatability with WASTE 1.2 and CW9
  23. //                         Restructured installation routines
  24.  
  25. #ifndef _WASTE_
  26. #include "WASTE.h"
  27. #endif
  28.  
  29. #include "WE_snd_Handler.h"
  30. #ifndef _WASTEOBJECTS_
  31. #include "WASTE_Objects.h"
  32. #endif
  33.  
  34. //
  35. // Local only routines
  36. //
  37.  
  38. static    OSErr    PlayCurrentGlobalSound( void );
  39. static    SndChannelPtr    CreateNewSoundChannel( void );
  40.  
  41. //
  42. // Sound Channel and current playing sound pointers
  43. //
  44. static SndChannelPtr    gSoundChannel = nil;
  45. static SndListHandle    gCurrentSound = nil;
  46. static short            gCurSoundHandleStatus = 0;
  47.  
  48. #define        kIsWASTESound        0x0100
  49.  
  50.  
  51.  
  52. void    InitSoundObjectHandler( void )
  53. {
  54. #if CREATE_CHANNEL_AT_INIT
  55.     gSoundChannel = CreateNewSoundChannel();
  56. #endif
  57. }
  58.  
  59.  
  60. OSErr    InstallSoundObject( WEReference theWE )
  61. {
  62. OSErr    iErr;
  63.  
  64. #ifdef __cplusplus
  65.     static WENewObjectUPP           newSndUPP = NewWENewObjectProc(HandleNewSound);
  66.     static WEDisposeObjectUPP       disposeSndUPP = NewWEDisposeObjectProc(HandleDisposeSound);
  67.     static WEDrawObjectUPP          drawSndUPP = NewWEDrawObjectProc(HandleDrawSound);
  68.     static WEClickObjectUPP         clickSndUPP = NewWEClickObjectProc(HandleClickSound);
  69. #else
  70.     static WENewObjectUPP           newSndUPP = NULL;
  71.     static WEDisposeObjectUPP       disposeSndUPP = NULL;
  72.     static WEDrawObjectUPP          drawSndUPP = NULL;
  73.     static WEClickObjectUPP         clickSndUPP = NULL;
  74.  
  75.     if ( newSndUPP == NULL )
  76.         newSndUPP = NewWENewObjectProc(HandleNewSound);
  77.     if ( disposeSndUPP == NULL )
  78.         disposeSndUPP = NewWEDisposeObjectProc(HandleDisposeSound);
  79.     if ( drawSndUPP == NULL )
  80.         drawSndUPP = NewWEDrawObjectProc(HandleDrawSound);
  81.     if ( clickSndUPP == NULL )
  82.         clickSndUPP = NewWEClickObjectProc(HandleClickSound);
  83. #endif
  84.  
  85.     if ( newSndUPP != NULL )
  86.         iErr = WEInstallObjectHandler(kTypeSound, weNewHandler, (UniversalProcPtr)newSndUPP, theWE);
  87.     else
  88.         iErr = weUnknownObjectTypeErr;
  89.     if (iErr) return(iErr);
  90.     
  91.     if ( disposeSndUPP != NULL )
  92.         iErr = WEInstallObjectHandler(kTypeSound, weDisposeHandler, (UniversalProcPtr)disposeSndUPP, theWE);
  93.     else
  94.         iErr = weUnknownObjectTypeErr;
  95.     if (iErr) return(iErr);
  96.     
  97.     if ( drawSndUPP != NULL )
  98.         iErr = WEInstallObjectHandler(kTypeSound, weDrawHandler, (UniversalProcPtr)drawSndUPP, theWE);
  99.     else
  100.         iErr = weUnknownObjectTypeErr;
  101.     if (iErr) return(iErr);
  102.     
  103.     if ( clickSndUPP != NULL )
  104.         iErr = WEInstallObjectHandler(kTypeSound, weClickHandler, (UniversalProcPtr)clickSndUPP, theWE);
  105.     else
  106.         iErr = weUnknownObjectTypeErr;
  107.     if (iErr) return(iErr);
  108.     
  109.     return(noErr);
  110. }
  111.  
  112. //
  113. // New Object Handler for sounds
  114. //
  115. pascal OSErr    HandleNewSound(Point *defaultObjectSize,WEObjectReference objectRef)
  116. {
  117. #pragma unused (objectRef)
  118.  
  119.     (*defaultObjectSize).h = 32;
  120.     (*defaultObjectSize).v = 32;
  121.  
  122.     return(noErr);
  123. }
  124. //
  125. // Dispose Object handler for sounds
  126. //
  127.  
  128. pascal OSErr    HandleDisposeSound(WEObjectReference objectRef )
  129. {
  130. SndListHandle    theSound;
  131.  
  132.     theSound = (SndListHandle)WEGetObjectDataHandle(objectRef);
  133.  
  134.     if (theSound == gCurrentSound)
  135.         StopCurrentSound();
  136.         
  137.     DisposeHandle((Handle)theSound);
  138.  
  139.     return(MemError());
  140. }
  141. //
  142. // Draw Object handler for sounds
  143. //
  144. pascal OSErr    HandleDrawSound(Rect *destRect, WEObjectReference objectRef )
  145. {
  146. #pragma unused (objectRef)
  147.  
  148. OSErr    iErr;
  149.     
  150.     iErr = PlotIconID(destRect,atNone,ttNone,kSoundIconID);
  151.     
  152.     return( iErr );
  153. }
  154. //
  155. // Click Object Handler for sounds
  156. //
  157.  
  158. pascal Boolean    HandleClickSound(    Point hitPt, 
  159.                             short modifiers, 
  160.                             long clickTime, 
  161.                             WEObjectReference objectRef)
  162. {
  163. #pragma unused ( hitPt, clickTime)
  164.  
  165. OSErr            iErr;
  166.  
  167.     if (modifiers & 0x0001)         // look for double-clicks
  168.     {
  169.         iErr = StopCurrentSound();
  170.         
  171.         gCurrentSound = (SndListHandle)WEGetObjectDataHandle( objectRef );
  172.         iErr = PlayCurrentGlobalSound();
  173.         gCurSoundHandleStatus += kIsWASTESound;
  174.         
  175.         if (!iErr)
  176.             return(true);
  177.         else
  178.         {
  179.             StopCurrentSound();
  180.             return(false);
  181.         }
  182.     }
  183.     else
  184.         return(false);
  185.  
  186. }
  187.  
  188. //
  189. // PlaySelectedSound()
  190. //        If a sound object, and only a sound object, is selected,
  191. //        PlaySelectedSound() will play it.
  192. //
  193. OSErr    PlaySelectedSound( WEReference theWE )
  194. {
  195. WEObjectReference    objectRef;
  196. SndListHandle        theSound;
  197. OSErr                iErr = noErr;
  198.  
  199.     iErr = WEGetSelectedObject( &objectRef, theWE );
  200.     if (!iErr)
  201.     {
  202.         theSound = (SndListHandle)WEGetObjectDataHandle( objectRef );
  203.         iErr = PlaySoundHandle( theSound );
  204.     }
  205.         
  206.     return( iErr );
  207. }
  208. //
  209. // CreateNewSoundObject()
  210. //        Uses built in sound recording to create a new sound object.
  211. //
  212. OSErr    CreateNewSoundObject( WEReference theWE )
  213. {
  214. OSErr            iErr;
  215. SndListHandle    sndHandle = nil;
  216. long            gestaltResponse;
  217. Point            corner = {32,32};
  218.  
  219.     iErr = Gestalt(gestaltSoundAttr, &gestaltResponse);
  220.     if ( (iErr == noErr)&&(gestaltResponse&gestaltHasSoundInputDevice))
  221.     {
  222.         iErr = SndRecord(nil,corner,siGoodQuality,&sndHandle);
  223.     
  224.         if (iErr == noErr)
  225.         {
  226.             corner.h = 32;
  227.             corner.v = 32;
  228.             WEInsertObject( kTypeSound, (Handle)sndHandle, corner, theWE );
  229.         }
  230.     }
  231.     return( iErr );
  232. }
  233.  
  234. //
  235. // PlaySoundHandle()
  236. //        Ultility routine to play a sound async.  Maintains a sound channel 
  237. //        and the sound data to do so. 
  238. //
  239. //        Intended for use by external code.
  240. //
  241.  
  242. OSErr    PlaySoundHandle( SndListHandle theSound )
  243. {
  244. OSErr        iErr = noErr;
  245.  
  246.     
  247.     // If a sound is currently playing, stop it and dispose of it's buffer.
  248.     iErr = StopCurrentSound();
  249.     
  250.     // create a new buffer for the selected sound.
  251.     gCurrentSound = theSound;
  252.     iErr = HandToHand((Handle *)&(gCurrentSound));
  253.     
  254.     if (!iErr)
  255.     {
  256.         iErr = PlayCurrentGlobalSound();
  257.         
  258.         if (iErr)
  259.         {
  260.             // FYI, HLock is called in PlayCurrentGlobalSound()
  261.             HUnlock( (Handle)gCurrentSound );
  262.             DisposeHandle( (Handle)gCurrentSound );
  263.             gCurrentSound = nil;
  264.         }    
  265.     }
  266.     
  267.     return(iErr);
  268. }
  269.  
  270. //
  271. // PlayCurrentGlobalSound()
  272. //        Used locally by the object handler to play the current sound.
  273. //
  274.  
  275. static    OSErr    PlayCurrentGlobalSound( void )
  276. {
  277. OSErr    iErr = noErr;
  278.  
  279.     // check for sound channel
  280.     if (!gSoundChannel)
  281.         gSoundChannel = CreateNewSoundChannel();
  282.  
  283.     if (gCurrentSound&&gSoundChannel)
  284.     {
  285.         // Lock the buffer and play the sound.
  286.         gCurSoundHandleStatus = HGetState( (Handle)gCurrentSound );
  287.         HLockHi( (Handle)gCurrentSound );
  288.         // FYI, gCurrentSound is unlocked and disposed of upon return to
  289.         // PlaySoundHandle()
  290.         
  291.         iErr = SndPlay(gSoundChannel,gCurrentSound,true);
  292.     }
  293.     
  294.     return(iErr);
  295. }
  296.  
  297. //
  298. // StopCurrentSound()
  299. //        Stops the current sound and returns memory to original state.
  300. //
  301.  
  302. OSErr    StopCurrentSound( void )
  303. {
  304. SndCommand    cmd;
  305. OSErr        iErr;
  306.  
  307.     if (gCurrentSound&&gSoundChannel)
  308.     {
  309.         cmd.cmd = quietCmd;
  310.         iErr = SndDoImmediate(gSoundChannel,&cmd);
  311.         
  312.         HSetState( (Handle)gCurrentSound, (char)(gCurSoundHandleStatus&0x00FF) );
  313.         
  314.         iErr = MemError();
  315.         if (iErr) return(iErr);
  316.         
  317.         if (!(gCurSoundHandleStatus&kIsWASTESound))
  318.             DisposeHandle( (Handle)gCurrentSound );
  319.             
  320.         gCurrentSound = nil;
  321.         gCurSoundHandleStatus = 0;
  322.         
  323.         return(MemError());
  324.     }
  325.  
  326.     return(noErr);
  327. }
  328. //
  329. // CreateNewSoundChannel()
  330. //        Used to create a new shound channel.
  331. //
  332. static SndChannelPtr    CreateNewSoundChannel( void )
  333. {
  334. OSErr            iErr;
  335. SndChannelPtr    chan;
  336.         
  337.     // allocate a sound channel
  338.     chan = (SndChannelPtr)NewPtrClear(sizeof(SndChannel));
  339.     if ( chan != nil ) 
  340.     {
  341.         chan->qLength = stdQLength;     //128 sound commands
  342.         iErr = SndNewChannel(&chan, sampledSynth, 0, nil);
  343.         if (iErr)
  344.         {
  345.             DisposePtr((Ptr)chan);
  346.             chan = nil;
  347.         }
  348.     }
  349.     return(chan);            // return SndChannelPtr
  350. }
  351.  
  352. //
  353. // CheckSoundStatus()
  354. //        Should be called periodically to dispose of unneeded sound buffers.
  355. //
  356. void CheckSoundStatus( void )
  357. {
  358.     if (!SoundIsPlaying())
  359.     {
  360.         HSetState( (Handle)gCurrentSound, (char)(gCurSoundHandleStatus&0x00FF) );
  361.                         
  362.         if (!gCurSoundHandleStatus&kIsWASTESound)
  363.             DisposeHandle( (Handle)gCurrentSound );
  364.             
  365.         gCurrentSound = nil;
  366.         gCurSoundHandleStatus = 0;
  367.     }        
  368. }
  369.  
  370. //
  371. // SoundIsPlaying()
  372. //        Returns true if a sound is being played by the object handler, 
  373. //        false if not.
  374. //
  375.  
  376. Boolean    SoundIsPlaying( void )
  377. {
  378. OSErr        iErr;
  379. SCStatus    theStatus;
  380.  
  381.     if (gSoundChannel)
  382.     {
  383.         iErr = SndChannelStatus(gSoundChannel,sizeof(SCStatus),&theStatus);
  384.         if (( theStatus.scChannelBusy )&&(gCurrentSound))
  385.             return( true );
  386.     }
  387.     
  388.     return( false );
  389. }